﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Collections;

namespace Departure
{
    public partial class ctrlTabControl : UserControl
    {
        #region Event Publication
        
        public event EventHandler SelectedIndexChanged;

        #endregion Event Publication

        #region Variables

        Point mouseDown = new Point(-1, -1);

        int tabHeight = 64;
        Point mouseTab = new Point(-1, -1);
        Rectangle tabRect = new Rectangle();
        int tabItem = 0;
        string tabName = "";

        bool vga = false;

        // Background drawing
        Bitmap backBufferBitmap;
        Graphics backBuffer;

        List<Control> ctrlTabPageCollection;
        int selectedIndex = -1;

        #endregion Variables

        #region Properties

        public int SelectedIndex 
        {
            get
            {
                return selectedIndex;
            }
            set
            {
                selectedIndex = value;
            }
        }

        public List<Control> TabPages 
        {
            get
            {
                return ctrlTabPageCollection;
            }
        }

        #endregion Properties

        #region Constructor

        public ctrlTabControl()
        {
            InitializeComponent();

            CreateBackBuffer();

            ctrlTabPageCollection = new List<Control>();

            tabRect = new Rectangle(0, this.ClientRectangle.Height - tabHeight, this.ClientRectangle.Width, tabHeight);
        }

        #endregion Constructor

        #region Event Subscription

        /// <summary>
        /// Called when the user clicks on the control with the mouse.
        /// </summary>
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);

            Capture = true;

            mouseDown.X = e.X;
            mouseDown.Y = e.Y;

            if (tabRect.Contains(mouseDown))
            {
                mouseTab.X = e.X;
                mouseTab.Y = e.Y;
                Invalidate();
            }
        }

        /// <summary>
        /// Called when the user moves the mouse over the control.
        /// </summary>
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            if (e.Button == MouseButtons.Left)
            {
                if (tabRect.Contains(mouseDown))
                {
                    mouseTab.X = e.X;
                    mouseTab.Y = e.Y;
                }
                Invalidate();
            }
        }

        /// <summary>
        /// Called when the user releases a mouse button.
        /// </summary>
        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            if (tabRect.Contains(mouseDown))
            {
                mouseTab.X = e.X;
                mouseTab.Y = e.Y;
            }
            mouseDown.Y = -1;
            Capture = false;
            Invalidate();
        }

        /// <summary>
        /// Called when the control is resized.
        /// </summary>
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            CreateBackBuffer();
            Reset();
        }

        /// <summary>
        /// Paints the background of the control.
        /// </summary>
        protected override void OnPaintBackground(PaintEventArgs e)
        {
            // Do nothing
        }

        /// <summary>
        /// Paints the control.
        /// </summary>
        protected override void OnPaint(PaintEventArgs e)
        {
            if (backBuffer != null)
            {
                backBuffer.Clear(Color.Black);
                
                int tabItemWidth = 0;
                if (this.ctrlTabPageCollection.Count > 0)
                    tabItemWidth = this.ClientRectangle.Width / this.ctrlTabPageCollection.Count;

                for (int i = 1; i < this.ctrlTabPageCollection.Count; i++)
                {
                    backBuffer.DrawLine(new Pen(Color.WhiteSmoke), i * tabItemWidth, tabRect.Y, i * tabItemWidth, tabRect.Y + tabRect.Height);
                }

                if (tabRect.Contains(mouseDown))
                {
                    if (this.ctrlTabPageCollection.Count > 0)
                        drawTabPreview(backBuffer, Bounds);
                }

                e.Graphics.DrawImage(backBufferBitmap, 0, 0);

            }
            else
            {
                base.OnPaint(e);
            }
        }

        #endregion Event Subscription

        #region Private Methods

        /// <summary>
        /// Cleans up the background paint buffer.
        /// </summary>
        private void CleanupBackBuffer()
        {
            if (backBufferBitmap != null)
            {
                backBufferBitmap.Dispose();
                backBufferBitmap = null;
                backBuffer.Dispose();
                backBuffer = null;
            }
        }

        /// <summary>
        /// Creates the background paint buffer.
        /// </summary>
        private void CreateBackBuffer()
        {
            CleanupBackBuffer();

            backBufferBitmap = new Bitmap(Bounds.Width, Bounds.Height);
            backBuffer = Graphics.FromImage(backBufferBitmap);
        }

        private void drawTabPreview(Graphics g, Rectangle bounds)
        {
            SizeF size;
            //g.DrawImage(skinSettings.FastAccess, new Rectangle((bounds.Width - skinSettings.FastAccess.Width) / 2, (bounds.Height - skinSettings.FastAccess.Height) / 2, skinSettings.FastAccess.Width, skinSettings.FastAccess.Height), new Rectangle(0, 0, skinSettings.FastAccess.Width, skinSettings.FastAccess.Height), GraphicsUnit.Pixel);

            using (Font f2 = AppropriateFont(g, 5, 200, new Size(bounds.Width, bounds.Height), getTabNameString(), this.Font, out size))
            {
                g.DrawString(getTabNameString(), f2, new SolidBrush(Color.WhiteSmoke), (bounds.Width - size.Width) / 2, (bounds.Height - size.Height) / 2);
            }
        }

        private Font AppropriateFont(Graphics g, float minFontSize, float maxFontSize, Size layoutSize, string s, Font f, out SizeF extent)
        {
            if (maxFontSize == minFontSize)
                f = new Font(f.Name, minFontSize, f.Style);

            extent = g.MeasureString(s, f);

            if (maxFontSize <= minFontSize)
                return f;

            float hRatio = layoutSize.Height / extent.Height;
            float wRatio = layoutSize.Width / extent.Width;
            float ratio = (hRatio < wRatio) ? hRatio : wRatio;

            float newSize = f.Size * ratio;

            if (newSize < minFontSize)
                newSize = minFontSize;
            else if (newSize > maxFontSize)
                newSize = maxFontSize;

            f = new Font(f.Name, newSize, f.Style);
            extent = g.MeasureString(s, f);

            return f;
        }

        private string getTabNameString()
        {
            int tabItemWidth = this.ClientRectangle.Width / this.ctrlTabPageCollection.Count;
            tabItem = mouseTab.X / tabItemWidth;
            if (this.ctrlTabPageCollection.Count >= tabItem)
            {
                tabName = this.ctrlTabPageCollection[tabItem].Text;
            }

            return tabName;
        }

        /// <summary>
        /// Resets the drawing of the list.
        /// </summary>
        private void Reset()
        {
            tabRect = new Rectangle(0, this.ClientRectangle.Height - tabHeight, this.ClientRectangle.Width, tabHeight);
            Invalidate();
        }

        #endregion Private Methods
        
    }
}
